﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace DiscoveryLogic.UI.Charts
{
    public class VisualElement : Control
    {
        #region const

        #endregion

        #region events 
        /// <summary>
        /// Handler for MouseLeftButtonDown event
        /// </summary>
        private event MouseButtonEventHandler _onMouseLeftButtonDown;

        /// <summary>
        /// Handler for MouseLeftButtonUp event
        /// </summary>
        private event MouseButtonEventHandler _onMouseLeftButtonUp;

        /// <summary>
        /// Handler for MouseEnter event
        /// </summary>
        private event EventHandler<MouseEventArgs> _onMouseEnter;

        /// <summary>
        /// Handler for MouseLeave event
        /// </summary>
        private event EventHandler<MouseEventArgs> _onMouseLeave;

        /// <summary>
        /// Handler for MouseMove event
        /// </summary>
        private event EventHandler<MouseEventArgs> _onMouseMove;

        internal event EventHandler EventChanged;

        [ScriptableMember]
        public new event MouseButtonEventHandler MouseLeftButtonDown
        {
            remove
            {
                _onMouseLeftButtonDown -= value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
            add
            {
                _onMouseLeftButtonDown += value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
        }

        [ScriptableMember]
        public new event MouseButtonEventHandler MouseLeftButtonUp
        {
            remove
            {
                _onMouseLeftButtonUp -= value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
            add
            {
                _onMouseLeftButtonUp += value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
        }

        [ScriptableMember]
        public new event EventHandler<MouseEventArgs> MouseEnter
        {
            remove
            {
                _onMouseEnter -= value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
            add
            {
                _onMouseEnter += value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
        }

        [ScriptableMember]
        public new event EventHandler<MouseEventArgs> MouseLeave
        {
            remove
            {
                _onMouseLeave -= value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
            add
            {
                _onMouseLeave += value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
        }

        [ScriptableMember]
        public new event EventHandler<MouseEventArgs> MouseMove
        {
            remove
            {
                _onMouseMove -= value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
            add
            {
                _onMouseMove += value;

                if (EventChanged != null)
                    EventChanged(this, null);
            }
        }

        #endregion

        #region fields

        private VisualControl _Control;
        private VisualElement _Element;
        private FrameworkElement _VisualObject;
        private string _TempHref;
        internal HrefTargets _TempHrefTarget;
        #endregion

        #region ctor
        public VisualElement()
        {
            
        }
        #endregion

        #region props
        public static DependencyProperty NameProperty =
            DependencyProperty.Register("Name",
            typeof(string), typeof(VisualElement), null);
        
        [ScriptableMember]
        public new string Name
        {
            get { return ((string)base.GetValue(NameProperty)); }
            set { base.SetValue(NameProperty, value); }
        }

        public static DependencyProperty ToolTipTextProperty =
            DependencyProperty.Register("ToolTipText",
            typeof(string), typeof(VisualElement),
            new PropertyMetadata(ToolTipTextPropertyChanged));

        public virtual string ToolTipText
        {
            get { return ((string)base.GetValue(ToolTipTextProperty)); }
            set { base.SetValue(ToolTipTextProperty, value); }
        }

        internal static void ToolTipTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as VisualElement).OnToolTipTextPropertyChanged((String)e.NewValue);
        }

        internal virtual void OnToolTipTextPropertyChanged(String newValue)
        {

        }

        public virtual string TextParser(String unParsed)
        {
            return unParsed;
        }
        #endregion

        #region public methods
        public void SetpropertyFromJs(string propertyName, string value)
        {
            JsHelper.SetProperty(this, propertyName, value);
        }

        internal static void AttachEvents2Visual(VisualElement obj, FrameworkElement visual)
        {
            if (visual != null)
                AttachEvents2Visual(obj, obj, visual);
        }

        internal static void AttachEvents2Visual(VisualElement obj, VisualElement senderElement, FrameworkElement visual)
        {
            if (visual == null)
                return;

            visual.MouseEnter += delegate(object sender, MouseEventArgs e)
            {
                if (obj._onMouseEnter != null)
                    obj._onMouseEnter(senderElement, e);
            };

            visual.MouseLeave += delegate(object sender, MouseEventArgs e)
            {
                if (obj._onMouseLeave != null)
                    obj._onMouseLeave(senderElement, e);
            };

            visual.MouseLeftButtonDown += delegate(object sender, MouseButtonEventArgs e)
            {
                if (obj._onMouseLeftButtonDown != null)
                    obj._onMouseLeftButtonDown(senderElement, e);
            };

            visual.MouseLeftButtonUp += delegate(object sender, MouseButtonEventArgs e)
            {
                if (obj._onMouseLeftButtonUp != null)
                    obj._onMouseLeftButtonUp(senderElement, e);
            };

            visual.MouseMove += delegate(object sender, MouseEventArgs e)
            {
                if (obj._onMouseMove != null)
                    obj._onMouseMove(senderElement, e);
            };
        }

        internal static void AttachEvents2Visual4MouseDownEvent(VisualElement obj, VisualElement senderElement, FrameworkElement visual)
        {
            if (visual == null)
                return;
        }

        public void AttachToolTip(VisualControl control, ObservableObject element, System.Collections.Generic.List<FrameworkElement> visualElements)
        {
            // Show ToolTip on mouse move over the chart element
            foreach (FrameworkElement visualElement in visualElements)
                AttachToolTip(control, element, visualElement);
        }

        internal void AttachToolTip(VisualControl control, VisualElement element, FrameworkElement visualObject)
        {
            if (visualObject == null || control == null || element == null)
                return;

            _Control = control;
            _Element = element;
            _VisualObject = visualObject;

            visualObject.MouseMove += new MouseEventHandler(VisualObject_MouseMove);
            visualObject.MouseEnter += new MouseEventHandler(VisualObject_MouseEnter);

            // Hide ToolTip on mouse leave from the chart element
            visualObject.MouseLeave += new MouseEventHandler(VisualObject_MouseLeave);
        }

        internal void DetachToolTip(FrameworkElement visualObject)
        {
            if (visualObject != null)
            {
                visualObject.MouseMove -= new MouseEventHandler(VisualObject_MouseMove);
                visualObject.MouseEnter -= new MouseEventHandler(VisualObject_MouseEnter);

                // Hide ToolTip on mouse leave from the chart element
                visualObject.MouseLeave -= new MouseEventHandler(VisualObject_MouseLeave);
            }
        }

        internal void AttachHref(VisualControl control, FrameworkElement element, String href, HrefTargets hrefTarget)
        {
            if (element == null)
                return;

            if (!String.IsNullOrEmpty(href))
            {
                _TempHref = href;
                _TempHrefTarget = hrefTarget;
                element.MouseEnter -= Element_MouseEnter;
                element.MouseEnter += Element_MouseEnter;

                element.MouseLeftButtonUp -= Element_MouseLeftButtonUp;
                element.MouseLeftButtonUp += new MouseButtonEventHandler(Element_MouseLeftButtonUp);
            }
        }
        #endregion

        #region private methods
        private void Element_MouseEnter(object sender, MouseEventArgs e)
        {
            (sender as FrameworkElement).Cursor = Cursors.Hand;
        }

        private void Element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(VisualControl.GetAbsolutePath(_TempHref)), _TempHrefTarget.ToString());
        }

        private void VisualObject_MouseLeave(object sender, MouseEventArgs e)
        {
            String text = _Element.TextParser(_Element.ToolTipText);
            if (_Control._ToolTip.Text == text)
                _Control._ToolTip.Hide();
        }

        private void VisualObject_MouseEnter(object sender, MouseEventArgs e)
        {
            if (!String.IsNullOrEmpty(_Control.ToolTipText) && _Control != _Element)
                return;

            UpdateToolTip(sender, e);
        }

        private void VisualObject_MouseMove(object sender, MouseEventArgs e)
        {
            if (!String.IsNullOrEmpty(_Control.ToolTipText) && _Control != _Element)
                return;
            UpdateToolTip(sender, e);
        }

        private void UpdateToolTip(object sender, MouseEventArgs e)
        {
            if (!String.IsNullOrEmpty(_Control.ToolTipText) && _Control != _Element)
                return;

            if (_Element.ToolTipText == null)
            {
                return;
            }
            else
            {
                String text = _Element.TextParser(_Element.ToolTipText);

                if (!String.IsNullOrEmpty(text))
                {
                    _Control._ToolTip.Text = text;

                    if (_Control.ToolTipEnabled)
                        _Control._ToolTip.Show();

                    (_Control as Chart).UpdateToolTipPosition(sender, e);
                }
            }
        }
        #endregion
    }
}
